﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ITProject.Repository.Abstract;
using ITProject.Domain;
using ITProject.WebUI.Models.ProjectAdmin;
using ITProject.Domain.Entities;
using ITProject.WebUI.Models;
using System.IO;
using System.Drawing;
using ITProject.WebUI.Models.Project;

namespace ITProject.WebUI.Controllers
{
    public partial class ProjectAdminController : Controller
    {

        public ProjectAdminController(IProjectRepository projectRepo, IUserRepository userRepo, IMessageRepository messageRepo)
        {
            projectRepository = projectRepo;
            userRepository = userRepo;
            messageRepository = messageRepo;
        }

        private IProjectRepository projectRepository;
        private IUserRepository userRepository;
        private IMessageRepository messageRepository;

        /// <summary>
        /// Metoda do zabezpieczenia się przed wykonywaniem czynności związanych z administracją projektu przez innego użytkonika niż zarządzający projektem.
        /// </summary>
        /// <param name="projectName">Nazwa projektu</param>
        /// <returns>Czy użytkownika ma prawo dostępu do panelu</returns>
        private bool CheckAccess(string projectName)
        {
            if (projectRepository.GetProjectUserRole(projectName, HttpContext.User.Identity.Name) != UserRole.Supervisor)
                return false;
            return true;
        }

        /// <summary>
        /// Metoda kontrolera do wygenerowania panelu administracyjnego projektu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Nazwa projektu</param>
        /// <returns>Panel administracyjny lub błąd spowodowany brakiem dostępu</returns>
        [Authorize]
        public virtual ActionResult Index(string projectName)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");;
            return View((object)projectName);
        }

        /// <summary>
        /// Metoda, która zbiera ifnormacje o uczestnikach projektu i wyświetla je w opodwiednim widoku.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Nazwa projektu</param>
        /// <returns>Widok do zarządzania użytkownikami w projekcie</returns>
        [Authorize]
        public virtual ActionResult ManageUser(string projectName)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");;
            ITProject.Domain.Entities.User[] users = userRepository.GetAllUsers();
            UserRole[] roles = new UserRole[users.Length];
            for (int i = 0; i < users.Length; i++)
                roles[i] = projectRepository.GetProjectUserRole(projectName, users[i].Login);
            int[] invitedUsers = projectRepository.GetIdInvitedUsers(projectName);
            ProjectAdminManageUserViewModel vm = ProjectAdminManageUserViewModel.Convert(users, roles, invitedUsers);
            User projectOwner = projectRepository.GetProjectOwner(projectName);
            if (projectOwner.Login == User.Identity.Name)
                vm.IsOwner = true;
            else
                vm.IsOwner = false;
            ViewData["ProjectName"] = projectName;
            return View(vm);
        }

        #region Edycja projektu

        [Authorize]
        public virtual ViewResult EditProject(string projectName)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            Project project = projectRepository.GetProjectByName(projectName);
            ProjectAdminEditProjectViewModel vm = ProjectAdminEditProjectViewModel.Convert(project);
            return View(vm);
        }

        [Authorize]
        [HttpPost]
        public virtual ActionResult EditProject(ProjectAdminEditProjectViewModel vm)
        {
            Project projectInDatabase = projectRepository.GetProjectById(vm.ProjectId);
            string projectName = projectInDatabase.Name;
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            string fileName = "";
            if (vm.Logo != null)
            {
                if (vm.Logo.ContentLength > 0)
                {
                    fileName = Path.GetFileName(vm.Logo.FileName);
                    int indexOfDot = fileName.LastIndexOf('.');
                    fileName = fileName.Insert(indexOfDot, DateTime.Now.ToString()).Replace(':', '.').Replace(" ", "");
                    var path = Path.Combine(HttpContext.Server.MapPath("/UserFiles/ProjectLogos/"), fileName);
                    if (vm.Logo.ContentType != "image/jpeg" && vm.Logo.ContentType != "image/png")
                        ModelState.AddModelError("Logo", "Plik musi być obrazkiem");
                    else
                    {
                        using (Image image = Image.FromStream(vm.Logo.InputStream, true, true))
                        {
                            if (image.Width < ProjectCreateViewModel.MaxLogoWidth && image.Height < ProjectCreateViewModel.MaxLogoHeight)
                            {
                                vm.Logo.SaveAs(path);
                                vm.DeleteLogo = true;
                            }
                            else
                                ModelState.AddModelError("Logo", "Obraz nie może być większy niż " + ProjectCreateViewModel.MaxLogoWidth +
                                    "x" + ProjectCreateViewModel.MaxLogoHeight);
                        }
                    }
                }
                else
                    vm.Logo = null;
                if (!ModelState.IsValid)
                    return View(MVC.ProjectAdmin.ActionNames.EditProject, vm);
            }
            if (vm.DeleteLogo)
            {
                // usunięcie starego loga
                string oldLogo = projectInDatabase.LogoPath;
                if (oldLogo != null) // usun logo
                {
                    string oldLogoPath = Path.Combine(HttpContext.Server.MapPath("/UserFiles/ProjectLogos/"), oldLogo);
                    if (System.IO.File.Exists(oldLogoPath))
                        System.IO.File.Delete(oldLogoPath);
                }
            }
            Project editedProject=ProjectAdminEditProjectViewModel.Convert(vm,fileName);
            projectRepository.EditProject(editedProject);
            return RedirectToAction(MVC.Project.ActionNames.Project, MVC.Project.Name, new { projectName=projectInDatabase.Name });
        }

        #endregion

        #region Zarządzanie zespołami w projekcie

        /// <summary>
        /// Metoda, która zbiera informacje o zespołach w projekcie i wyświetla je w opodwiednim widoku.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Nazwa projektu.</param>
        /// <returns>Widok do zarządzania zespołami w projekcie.</returns>
        [Authorize]
        public virtual ActionResult ManageTeam(string projectName)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            IEnumerable<Team> teams = projectRepository.GetProjectTeams(projectName);
            ProjectAdminManageTeamViewModel vm = ProjectAdminManageTeamViewModel.Convert(teams);
            ViewData["ProjectName"] = projectName;
            return View(vm);
        }

        /// <summary>
        /// Metoda, która pozwala stworzyć zespół w ramach danego projektu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Nazwa projektu.</param>
        /// <returns>Widok umożliwiający stworzenie nowego projektu.</returns>
        [Authorize]
        public virtual ActionResult CreateTeam(string projectName)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            ProjectAdminCreateTeamViewModel vm = new ProjectAdminCreateTeamViewModel();
            User[] projectUsers;
            UserRole[] projectUserRole;
            projectRepository.GetProjectUsers(out projectUsers, out projectUserRole, projectName);
            ProjectAdminCreateTeamViewModel.CompleteProjectUsers(vm, projectName, projectUsers);
            vm.ProjectId = projectRepository.GetProjectId(projectName);
            ViewData["ProjectName"] = projectName;
            return View(vm);
        }

        /// <summary>
        /// Metoda, która tworzy zespół w ramach danego projektu.
        /// Autor: Jakub Szatkowksi
        /// </summary>
        /// <param name="vm">Model widokowy tworzenia zespołu.</param>
        /// <returns>Przekierowanie do akcji wyświetlającej zarządzanie zespołami w projekcie.</returns>
        [HttpPost]
        [Authorize]
        public virtual ActionResult CreateTeam(ProjectAdminCreateTeamViewModel vm)
        {
            string projectName = projectRepository.GetProjectById(vm.ProjectId).Name;
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            IEnumerable<Team> projectTeams = projectRepository.GetProjectTeams(projectName);
            foreach (Team t in projectTeams)
            {
                if (t.Name == vm.Name)
                {
                    ModelState.AddModelError("Name", "W projekcie " + projectName + " istnieje już zespół o takiej nazwie");
                    User[] projectUsers;
                    UserRole[] projectUserRole;
                    projectRepository.GetProjectUsers(out projectUsers, out projectUserRole, projectName);
                    ProjectAdminCreateTeamViewModel.CompleteProjectUsers(vm, projectName, projectUsers);
                    ViewData["ProjectName"] = projectName;
                    return View(vm);
                }
            }
            User leader = userRepository.GetUserByLogin(vm.Leader);
            Team team = ProjectAdminCreateTeamViewModel.Convert(vm, leader.Id);
            projectRepository.AddNewTeam(team);
            return RedirectToAction(MVC.ProjectAdmin.ActionNames.ManageTeam, new { projectName = projectName });
        }

        [Authorize]
        public virtual ActionResult AddUserToTeam(string projectName, string teamName, string userlogin)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            int iduser = userRepository.GetUserByLogin(userlogin).Id;
            int idproject = projectRepository.GetProjectId(projectName);
            int idTeam = projectRepository.GetTeamId(teamName, idproject);
            projectRepository.AddUserToTeam(idTeam, iduser);
            return RedirectToAction(MVC.ProjectAdmin.ActionNames.ManageTeamUsers, new { projectName = projectName, teamName = teamName });
        }

        [Authorize]
        public virtual ActionResult RemoveUserFromTeam(string projectName, string teamName, string userlogin)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            int iduser = userRepository.GetUserByLogin(userlogin).Id;
            int idproject = projectRepository.GetProjectId(projectName);
            int idTeam = projectRepository.GetTeamId(teamName, idproject);
            projectRepository.RemoveUserFromTeam(idTeam, iduser);
            return RedirectToAction(MVC.ProjectAdmin.ActionNames.ManageTeamUsers, new { projectName = projectName, teamName = teamName });
        }

        [Authorize]
        public virtual ActionResult ManageTeamUsers(string projectName, string teamName)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            int idproject = projectRepository.GetProjectId(projectName);
            int idteam = projectRepository.GetTeamId(teamName, idproject);
            string lider = projectRepository.GetTeamLeader(idteam);
            IEnumerable<String> usersT = projectRepository.GetTeamUsers(idteam);
            IEnumerable<String> Allusers = projectRepository.GetProjectUsersLogin(idproject);
            IEnumerable<String> NoUsers = Allusers.Except(usersT).Except(new List<string> { lider }).ToList();

            ProjectAdminManageTeamUserViewModel vm = ProjectAdminManageTeamUserViewModel.Convert(usersT, NoUsers, teamName);
            ViewData["ProjectName"] = projectName;
            return View(vm);

        }

        [Authorize]
        public virtual ActionResult EditTeam(string projectName, string teamName)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            int idproject = projectRepository.GetProjectId(projectName);
            int idTeam = projectRepository.GetTeamId(teamName, idproject);
            Team team = projectRepository.GetTeamById(idTeam);
            string leader = projectRepository.GetTeamLeader(idTeam);
            ProjectAdminEditTeamViewModel vm = ProjectAdminEditTeamViewModel.Convert(team, leader, projectRepository.GetTeamUsers(idTeam).ToArray());
            vm.ProjectName = projectName;
            return View(vm);
        }

        [Authorize]
        [HttpPost]
        public virtual ActionResult EditTeam(ProjectAdminEditTeamViewModel vm)
        {
            string projectName = vm.ProjectName;
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            IEnumerable<Team> projectTeams = projectRepository.GetProjectTeams(projectName);
            foreach (Team t in projectTeams)
            {
                if (t.Name == vm.Name && t.Id != vm.TeamId)
                {
                    ModelState.AddModelError("Name", "W projekcie " + projectName + " istnieje już zespół o takiej nazwie");
                    ProjectAdminEditTeamViewModel.CompleteTeamUsers(vm, vm.LeaderLogin, projectRepository.GetTeamUsers(vm.TeamId).ToArray());
                    ViewData["ProjectName"] = projectName;
                    return View(vm);
                }
            }
            Team team = ProjectAdminEditTeamViewModel.Convert(vm, userRepository.GetUserByLogin(vm.LeaderLogin).Id);
            projectRepository.EditTeam(team);
            return RedirectToAction(MVC.ProjectAdmin.ActionNames.ManageTeam, new { projectName = projectName });
        }

        #endregion

        #region zapraszanie użytkownika do projektu

        /// <summary>
        /// Metoda, która fizycznie wysyła zaproszenie do użytkownika.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Nazwa projektu.</param>
        /// <param name="userName">Nazwa użytkownika zapraszanego.</param>
        private void InviteOneUser(string projectName, string userName)
        {
            string superVisorName = HttpContext.User.Identity.Name;
            int superVisorId = userRepository.GetUserByLogin(HttpContext.User.Identity.Name).Id;
            int projectId = projectRepository.GetProjectId(projectName);
            int idUser = userRepository.GetUserByLogin(userName).Id;
            projectRepository.Invite(projectId, idUser);
            // wyslanie wiadomosci
            Message mes = new Message();
            mes.ReadConfrimation = false;
            mes.Sender = superVisorId;
            mes.Receiver = idUser;
            string acceptRejectString = "p" + projectId + "u" + idUser;
            // format zaproszenia uczestnika 10 do projektu 12 to acceptString=p12u10
            string urlYes = @"http://localhost:8081/Project/AcceptInvitation?acceptString=" + acceptRejectString;
            string urlNo = @"http://localhost:8081/Project/RejectInvitation?rejectString=" + acceptRejectString;
            mes.Subject = "Zaproszenie do projetktu " + projectName;
            mes.Text = "Zostałeś zaproszony do projektu " + projectName + " przez użytkownika " + superVisorName + ".<br/>Czy przyjmujesz zaproszenie? <a href=\"" + urlYes + "\">Tak</a> <a href=\"" + urlNo + "\">Nie</a>";
            messageRepository.Send(mes);
        }

        /*/// <summary>
        /// Metoda, która zaprasza do danego projektu danych jej uczestników.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Nazwa projektu.</param>
        /// <param name="userNames">Użytkownicy, którym wysłane zostaje zaproszenie.</param>
        /// <returns>Błąd lub widok zarządzania uczestnikami projektu.</returns>
        [Authorize]
        public virtual ActionResult InviteUsers(string projectName, List<NoProjectUserListItem> users)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");

            foreach (NoProjectUserListItem user in users )
            {
                if (user.Selected == false)
                    continue;
                InviteOneUser(projectName, user.Text);
            }
            return RedirectToAction(MVC.ProjectAdmin.ActionNames.ManageUser, new { projectName = projectName });
        }*/

        /// <summary>
        /// Metoda, która zaprasza wybranego użytkownika do projektu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Nazwa projektu.</param>
        /// <param name="user">Nazwa użytkownika z listy.</param>
        /// <returns>Błąd lub widok zarządzania uczestnikami projektu.</returns>
        [Authorize]
        public virtual ActionResult InviteUser(string projectName, string user)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            InviteOneUser(projectName, user);
            return RedirectToAction(MVC.ProjectAdmin.ActionNames.ManageUser, new { projectName = projectName });
        }

        #endregion

        #region usuwanie użytkownika

        /// <summary>
        /// Metoda, która usuwa wybranego użytkownika z projektu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Nazwa projektu.</param>
        /// <param name="user">Nazwa użytkownika z listy.</param>
        /// <returns>Błąd lub widok zarządzania uczestnikami projektu.</returns>
        [Authorize]
        public virtual ActionResult DeleteUser(string projectName, string user)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            DeleteOneUser(projectName, user);
            return RedirectToAction(MVC.ProjectAdmin.ActionNames.ManageUser, new { projectName = projectName });
        }

        /// <summary>
        /// Metoda, która fizycznie usuwa użytkownika z projektu po czym wysyła wiadomość do tego użytkownika.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Nazwa projektu.</param>
        /// <param name="userName">Nazwa usuwanego użytkownika.</param>
        [Authorize]
        private void DeleteOneUser(string projectName, string userName)
        {
            int projectId = projectRepository.GetProjectId(projectName);
            int userId = userRepository.GetUserByLogin(userName).Id;
            bool result = projectRepository.DeleteUserFromProject(projectId, userId);
            if (!result)
                ; // TO DO: wyświetlenie okna z błedami
            int superVisorId = userRepository.GetUserByLogin(HttpContext.User.Identity.Name).Id;
            Message mes = new Message();
            mes.ReadConfrimation = false;
            mes.Sender = superVisorId;
            mes.Receiver = userId;
            mes.Subject = "Usunięcie z projektu " + projectName;
            mes.Text = "Zostałeś usunięty z projektu " + projectName + " skontaktuj się z administratorem projektu w celu poznania powodu";
            messageRepository.Send(mes);
        }

        #endregion

        #region edycja roli

        [Authorize]
        public virtual ActionResult EditUserRole(string projekt, string user, int Role)
        {
            if (!CheckAccess(projekt))
                return View(MVC.Shared.Views.Error);
            int iduser = userRepository.GetUserByLogin(user).Id;
            int idproject = projectRepository.GetProjectByName(projekt).Id;
            projectRepository.EditRole(iduser, Role, idproject);
            return RedirectToAction(MVC.ProjectAdmin.ActionNames.ManageUser, new { projectName = projekt });
        }
        #endregion

        #region Zarządzanie relesami

        [Authorize]
        public virtual ViewResult ProjectReleases(string projectName)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            int projectId = projectRepository.GetProjectId(projectName);
            Release[] releases = projectRepository.GetProjectReleases(projectId);
            ProjectAdminProjectReleaseViewModel[] vm = ProjectAdminProjectReleaseViewModel.Convert(releases);
            ViewData["ProjectName"] = projectName;
            return View(vm);
        }

        [Authorize]
        public virtual ViewResult ChangeReleaseStatus(string projectName, string releaseName, string currentReleaseStatus)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            ProjectAdminChangeReleaseStatusViewModel vm = ProjectAdminChangeReleaseStatusViewModel.Convert(projectName, releaseName, currentReleaseStatus);
            return View(vm);
        }

        [Authorize]
        [HttpPost]
        public virtual ActionResult ChangeReleaseStatus(ProjectAdminChangeReleaseStatusViewModel vm)
        {
            string projectName = vm.ProjectName;
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            int projectId = projectRepository.GetProjectId(projectName);
            Release release = projectRepository.GetReleaseByName(vm.ReleaseName, projectId);
            Status status = StatusName.ConvertFromString(vm.ReturnStatus);
            if ((byte)status != release.Status)
                projectRepository.ChangeReleaseStatus(release, status, vm.Comment, userRepository.GetUserByLogin(User.Identity.Name).Id);
            return RedirectToAction(MVC.ProjectAdmin.ActionNames.ProjectReleases, new { projectName = projectName });
        }

        [Authorize]
        public virtual ActionResult CreateRelease(string projectName)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            ProjectAdminCreateReleaseViewModel vm = new ProjectAdminCreateReleaseViewModel();
            vm.ProjectName = projectName;
            vm.PlannedEndDate = DateTime.Now.AddDays(7);
            return View(vm);
        }

        [Authorize]
        [HttpPost]
        public virtual ActionResult CreateRelease(ProjectAdminCreateReleaseViewModel vm)
        {
            string projectName = vm.ProjectName;
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            int projectId = projectRepository.GetProjectId(projectName);
            // sprawdzenie czy nie ma releasu o takiej nazwie
            Release[] releases = projectRepository.GetProjectReleases(projectId);
            for (int i = 0; i < releases.Length; i++)
            {
                if (releases[i].Name == vm.Name)
                {
                    ModelState.AddModelError("Name", "W projekcie już istnieje wersja o takiej nazwie");
                    return View(vm);
                }
            }
            Release release = ProjectAdminCreateReleaseViewModel.Convert(vm, projectId);
            projectRepository.AddNewRelease(release, userRepository.GetUserByLogin(User.Identity.Name).Id);
            return RedirectToAction(MVC.ProjectAdmin.ActionNames.ProjectReleases, new { projectName = projectName });
        }

        [Authorize]
        public virtual ActionResult EditRelease(string projectName, string releaseName)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            int projectId = projectRepository.GetProjectId(projectName);
            Release release = projectRepository.GetReleaseByName(releaseName, projectId);
            ProjectAdminEditReleaseViewModel vm = ProjectAdminEditReleaseViewModel.Convert(release, projectName);
            return View(vm);
        }

        [Authorize]
        [HttpPost]
        public virtual ActionResult EditRelease(ProjectAdminEditReleaseViewModel vm)
        {
            string projectName = vm.ProjectName;
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            // sprawdzenie czy nie ma releasu o takiej nazwie
            int projectId = projectRepository.GetProjectId(projectName);
            Release[] releases = projectRepository.GetProjectReleases(projectId);
            for (int i = 0; i < releases.Length; i++)
            {
                if (releases[i].Name == vm.Name && releases[i].Id != vm.ReleaseId)
                {
                    ModelState.AddModelError("Name", "W projekcie już istnieje wersja o takiej nazwie");
                    return View(vm);
                }
            }
            Release release = ProjectAdminEditReleaseViewModel.Convert(vm);
            projectRepository.EditRelease(release);
            return RedirectToAction(MVC.ProjectAdmin.ActionNames.ProjectReleases, new { projectName = projectName });
        }

        #endregion

        #region Zarządzanie wymaganiami funkcjonalnymi

        [Authorize]
        public virtual ViewResult FunctionalRequirements(string projectName)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            int projectId = projectRepository.GetProjectId(projectName);
            FunctionalRequirement[] requirements = projectRepository.GetProjectFunctionalRequirements(projectId);
            ProjectAdminFunctionalRequirementViewModel[] vmTab = ProjectAdminFunctionalRequirementViewModel.Convert(requirements);
            ViewData["ProjectName"] = projectName;
            return View(vmTab);
        }

        [Authorize]
        public virtual ViewResult AddNewFunctionalRequirement(string projectName)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            ProjectAdminAddNewFunctionalRequirement vm = new ProjectAdminAddNewFunctionalRequirement();
            vm.ProjectName = projectName;
            return View(vm);
        }

        [HttpPost]
        [Authorize]
        public virtual ActionResult AddNewFunctionalRequirement(FormCollection fc)
        {
            string projectName = fc["ProjectName"];
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            int projectId = projectRepository.GetProjectId(projectName);
            // sprawdzenie czy nazwa nie jest pusta i czy czasem nie ma już nazwy wymagania w projekcie
            if (fc["Name"] == null || fc["Name"] == "")
            {
                ViewData["ErrorNameMessage"] = "Musisz podać nazwę wymagania";
                ProjectAdminAddNewFunctionalRequirement vm = new ProjectAdminAddNewFunctionalRequirement();
                vm.CompleteFromForm(fc);
                vm.ProjectName = projectName;
                return View(vm);
            }
            FunctionalRequirement[] requirements = projectRepository.GetProjectFunctionalRequirements(projectId);
            for (int i = 0; i < requirements.Length; i++)
                if (requirements[i].Name == fc["Name"])
                {
                    ViewData["ErrorNameMessage"] = "Istanieje już wymaganie o takiej nazwie w projekcie";
                    ProjectAdminAddNewFunctionalRequirement vm = new ProjectAdminAddNewFunctionalRequirement();
                    vm.CompleteFromForm(fc);
                    vm.ProjectName = projectName;
                    return View(vm);
                }

            int userId = userRepository.GetUserByLogin(User.Identity.Name).Id;
            // dodanie wymagania
            FunctionalRequirement requirement = ProjectAdminAddNewFunctionalRequirement.Convert(fc, projectId, userId);
            int requirementId = projectRepository.AddFunctionalRequirement(requirement);
            // teraz dodajemy wymagania do projektu
            int? maxId = projectRepository.GetMaxScenarioId();
            int minId = 1;
            if (maxId != null)
                minId = (int)maxId + 1;
            List<Scenario> scenarios = ProjectAdminAddNewFunctionalRequirement.MakeScenariosFromForm(fc, requirementId, minId);
            projectRepository.AddScenarios(scenarios);
            return RedirectToAction(MVC.ProjectAdmin.ActionNames.FunctionalRequirements, new { projectName = projectName });
        }

        [Authorize]
        public virtual ActionResult DeleteFunctionRequirement(string projectName, int requirementId)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            projectRepository.DeleteFunctionalRequirement(requirementId);
            return RedirectToAction(MVC.ProjectAdmin.ActionNames.FunctionalRequirements, new { projectName = projectName });
        }

        #endregion

        #region Zarządzanie funkcjonalnościami

        /// <summary>
        /// Metoda wywołująca widok listy funkcjonalności w projekcie.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Nazwa projektu.</param>
        /// <returns>Widok listy funkcjonalności w projekcie.</returns>
        [Authorize]
        public virtual ViewResult ProjectFeatures(string projectName)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            int projectId = projectRepository.GetProjectId(projectName);
            Feature[] features = projectRepository.GetProjectFeatures(projectId);
            string[] receivers = new string[features.Length];
            for (int i = 0; i < receivers.Length; i++)
            {
                if (features[i].IsToTeam)
                    receivers[i] = projectRepository.GetFeatureTeamByFeatureId(features[i].Id).Name;
                else
                    receivers[i] = projectRepository.GetFeatureUserByFeatureId(features[i].Id).Login;
            }
            ProjectAdminProjectFeatureViewModel[] vmTab = ProjectAdminProjectFeatureViewModel.Convert(features, receivers);
            ViewData["ProjectName"] = projectName;
            return View(vmTab);
        }

        /// <summary>
        /// Metoda pozwalająca na dodanie nowej funkcjonalności do projektu. Tworzy model widokowy i uzupełnia odpowiednie listy.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Nazwa projektu.</param>
        /// <returns>Widok formularza nowej funkcjonalności.</returns>
        [Authorize]
        public virtual ViewResult AddNewFeature(string projectName)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            int projectId = projectRepository.GetProjectId(projectName);
            Release[] releases = projectRepository.GetProjectReleases(projectId);
            User[] users;
            UserRole[] userRoles;
            projectRepository.GetProjectUsers(out users, out userRoles, projectName);
            Team[] teams = projectRepository.GetProjectTeams(projectName).ToArray();
            ProjectAdminAddNewFeatureViewModel vm = new ProjectAdminAddNewFeatureViewModel();
            vm.ProjectName = projectName;

            // uzupełnienie odpowiednich list
            vm.ReleaseList = new List<SelectListItem>(releases.Length + 1);
            SelectListItem noRelease = new SelectListItem { Selected = true, Text = ProjectAdminAddNewFeatureViewModel.NoRelease };
            vm.ReleaseList.Add(noRelease);
            for (int i = 0; i < releases.Length; i++)
                vm.ReleaseList.Add(new SelectListItem { Text = releases[i].Name });
            vm.UserList = new List<SelectListItem>(users.Length);
            for (int i = 0; i < users.Length; i++)
                vm.UserList.Add(new SelectListItem { Text = users[i].Login });
            vm.TeamList = new List<SelectListItem>(teams.Length);
            for (int i = 0; i < teams.Length; i++)
                vm.TeamList.Add(new SelectListItem { Text = teams[i].Name });

            // domyślna data dzisiaj plus tydzien
            vm.PlannedEndDate = DateTime.Now.AddDays(7);
            return View(vm);
        }

        /// <summary>
        /// Metoda pozwala dodać nową funkcjonalność do projektu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="vm">Model widokowy nowej funkcjonalności.</param>
        /// <returns>Lista funkcjonalności w projekcie.</returns>
        [Authorize]
        [HttpPost]
        public virtual ActionResult AddNewFeature(ProjectAdminAddNewFeatureViewModel vm)
        {
            string projectName = vm.ProjectName;
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            int projectId = projectRepository.GetProjectId(projectName);
            // sprawdzenie czy nie istnieje juz nazwa funkcjonalności
            Feature[] features = projectRepository.GetProjectFeatures(projectId);
            for (int i = 0; i < features.Length; i++)
                if (vm.Name == features[i].Name)
                {
                    ModelState.AddModelError("Name", "Już isnieje w projekcie funkcjonalność o podanej nazwie");
                    // uzupełnienie odpowiednich list
                    Release[] releases = projectRepository.GetProjectReleases(projectId);
                    User[] users;
                    UserRole[] userRoles;
                    projectRepository.GetProjectUsers(out users, out userRoles, projectName);
                    Team[] teams = projectRepository.GetProjectTeams(projectName).ToArray();

                    vm.ReleaseList = new List<SelectListItem>(releases.Length + 1);
                    SelectListItem noRelease = new SelectListItem { Selected = true, Text = ProjectAdminAddNewFeatureViewModel.NoRelease };
                    vm.ReleaseList.Add(noRelease);
                    for (int j = 0; j < releases.Length; j++)
                        vm.ReleaseList.Add(new SelectListItem { Text = releases[j].Name });
                    vm.UserList = new List<SelectListItem>(users.Length);
                    for (int j = 0; j < users.Length; j++)
                        vm.UserList.Add(new SelectListItem { Text = users[j].Login });
                    vm.TeamList = new List<SelectListItem>(teams.Length);
                    for (int j = 0; j < teams.Length; j++)
                        vm.TeamList.Add(new SelectListItem { Text = teams[j].Name });
                    return View(vm);
                }
            int? releaseId = null;
            if (vm.ReturnVersion != ProjectAdminAddNewFeatureViewModel.NoRelease)
                releaseId = projectRepository.GetReleaseByName(vm.ReturnVersion, projectId).Id;
            Feature feature = ProjectAdminAddNewFeatureViewModel.Convert(vm, projectId, releaseId);
            string userTeam = feature.IsToTeam ? vm.ReturnTeam : vm.ReturnUser;
            int creatorId = userRepository.GetUserByLogin(User.Identity.Name).Id;
            projectRepository.AddNewFeature(feature, userTeam, creatorId);
            return RedirectToAction(MVC.ProjectAdmin.ActionNames.ProjectFeatures, new { projectName = projectName });
        }

        /// <summary>
        /// Metoda generująca widok pozwalający edytować funkcjonalność.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Nazwa projektu.</param>
        /// <param name="featureId">Identyfikator funkcjonalności do edycji.</param>
        /// <returns>Widok pozwalający edytować funkcjonalność.</returns>
        [Authorize]
        public virtual ViewResult EditFeature(string projectName, int featureId)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            Feature feature = projectRepository.GetFeatureById(featureId);
            Team featureTeam;
            User featureUser;
            if (feature.IsToTeam)
                featureTeam = projectRepository.GetFeatureTeamByFeatureId(featureId);
            else
                featureUser = projectRepository.GetFeatureUserByFeatureId(featureId);
            ProjectAdminEditFeatureViewModel vm = ProjectAdminEditFeatureViewModel.Convert(feature, projectName);

            // uzupelnienie odpowiednich list modelu widokowego
            int projectId = projectRepository.GetProjectId(projectName);
            Release[] releases = projectRepository.GetProjectReleases(projectId);
            User[] users;
            UserRole[] userRoles;
            projectRepository.GetProjectUsers(out users, out userRoles, projectName);
            Team[] teams = projectRepository.GetProjectTeams(projectName).ToArray();

            // lista releasów
            vm.ReleaseList = new List<SelectListItem>(releases.Length + 1);
            SelectListItem noRelease = new SelectListItem { Text = ProjectAdminAddNewFeatureViewModel.NoRelease };
            if (feature.ReleaseId == null)
                noRelease.Selected = true;
            else
            {
                Release release = projectRepository.GetReleaseById((int)feature.ReleaseId);
                SelectListItem actualRelease = new SelectListItem { Selected = true, Text = release.Name };
                vm.ReleaseList.Add(actualRelease);
                noRelease.Selected = false;
            }
            vm.ReleaseList.Add(noRelease);
            for (int i = 0; i < releases.Length; i++)
            {
                if (releases[i].Id != feature.ReleaseId)
                    vm.ReleaseList.Add(new SelectListItem { Text = releases[i].Name });
            }

            // lista przypisanych uzytkownikow, zakłądamy że żaden user nie ma id równe -1
            vm.UserList = new List<SelectListItem>(users.Length);
            int actualUserId = -1;
            if (!feature.IsToTeam)
            {
                User actualUser = projectRepository.GetFeatureUserByFeatureId(featureId);
                SelectListItem actualUserItem = new SelectListItem { Selected = true, Text = actualUser.Login };
                actualUserId = actualUser.Id;
                vm.UserList.Add(actualUserItem);
            }
            for (int i = 0; i < users.Length; i++)
            {
                if (users[i].Id != actualUserId)
                    vm.UserList.Add(new SelectListItem { Text = users[i].Login });
            }

            // lista przypisanych teamów, zakładamy, że żaden team nie ma id równe -1
            vm.TeamList = new List<SelectListItem>(teams.Length);
            int actualTeamId = -1;
            if (feature.IsToTeam)
            {
                Team actualTeam = projectRepository.GetFeatureTeamByFeatureId(featureId);
                SelectListItem actualTeamItem = new SelectListItem { Selected = true, Text = actualTeam.Name };
                actualTeamId = actualTeam.Id;
                vm.TeamList.Add(actualTeamItem);
            }
            for (int i = 0; i < teams.Length; i++)
            {
                if (teams[i].Id != actualTeamId)
                    vm.TeamList.Add(new SelectListItem { Text = teams[i].Name });
            }
            return View(vm);
        }

        /// <summary>
        /// Metoda HttpPost do edycji funkcjonalności.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="vm">Model z widoku.</param>
        /// <returns>Akcja wyświetlająca listę funkcjonalności.</returns>
        [Authorize]
        [HttpPost]
        public virtual ActionResult EditFeature(ProjectAdminEditFeatureViewModel vm)
        {
            string projectName = vm.ProjectName;
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            int projectId = projectRepository.GetProjectId(projectName);
            // sprawdzenie czy nie istnieje juz nazwa funkcjonalności
            Feature[] features = projectRepository.GetProjectFeatures(projectId);
            for (int j = 0; j < features.Length; j++)
                if (vm.Name == features[j].Name && vm.FeatureId != features[j].Id)
                {
                    ModelState.AddModelError("Name", "Istnieje w projekcie funkcjonalność o podanej nazwie");
                    // uzupelnienie odpowiednich list modelu widokowego
                    Release[] releases = projectRepository.GetProjectReleases(projectId);
                    User[] users;
                    UserRole[] userRoles;
                    projectRepository.GetProjectUsers(out users, out userRoles, projectName);
                    Team[] teams = projectRepository.GetProjectTeams(projectName).ToArray();
                    Feature feature = projectRepository.GetFeatureById(vm.FeatureId);
                    // lista releasów
                    vm.ReleaseList = new List<SelectListItem>(releases.Length + 1);
                    SelectListItem noRelease = new SelectListItem { Text = ProjectAdminAddNewFeatureViewModel.NoRelease };
                    if (feature.ReleaseId == null)
                        noRelease.Selected = true;
                    else
                    {
                        Release release = projectRepository.GetReleaseById((int)feature.ReleaseId);
                        SelectListItem actualRelease = new SelectListItem { Selected = true, Text = release.Name };
                        vm.ReleaseList.Add(actualRelease);
                        noRelease.Selected = false;
                    }
                    vm.ReleaseList.Add(noRelease);
                    for (int i = 0; i < releases.Length; i++)
                    {
                        if (releases[i].Id != feature.ReleaseId)
                            vm.ReleaseList.Add(new SelectListItem { Text = releases[i].Name });
                    }

                    // lista przypisanych uzytkownikow, zakłądamy że żaden user nie ma id równe -1
                    vm.UserList = new List<SelectListItem>(users.Length);
                    int actualUserId = -1;
                    if (!feature.IsToTeam)
                    {
                        User actualUser = projectRepository.GetFeatureUserByFeatureId(feature.Id);
                        SelectListItem actualUserItem = new SelectListItem { Selected = true, Text = actualUser.Login };
                        actualUserId = actualUser.Id;
                        vm.UserList.Add(actualUserItem);
                    }
                    for (int i = 0; i < users.Length; i++)
                    {
                        if (users[i].Id != actualUserId)
                            vm.UserList.Add(new SelectListItem { Text = users[i].Login });
                    }

                    // lista przypisanych teamów, zakładamy, że żaden team nie ma id równe -1
                    vm.TeamList = new List<SelectListItem>(teams.Length);
                    int actualTeamId = -1;
                    if (feature.IsToTeam)
                    {
                        Team actualTeam = projectRepository.GetFeatureTeamByFeatureId(feature.Id);
                        SelectListItem actualTeamItem = new SelectListItem { Selected = true, Text = actualTeam.Name };
                        actualTeamId = actualTeam.Id;
                        vm.TeamList.Add(actualTeamItem);
                    }
                    for (int i = 0; i < teams.Length; i++)
                    {
                        if (teams[i].Id != actualTeamId)
                            vm.TeamList.Add(new SelectListItem { Text = teams[i].Name });
                    }
                    vm.PriorityList = new PriorityViewModel(PriorityViewModel.ConvertFromString(PriorityViewModel.ConvertFromByte(feature.Priority)));
                    return View(vm);
                }
            // czas na edycje featura
            int? releaseId = null;
            if (vm.ReturnVersion != ProjectAdminAddNewFeatureViewModel.NoRelease)
            {
                Release release = projectRepository.GetReleaseByName(vm.ReturnVersion, projectId);
                releaseId = release.Id;
            }
            Feature editFeature = ProjectAdminEditFeatureViewModel.Convert(vm, releaseId);
            projectRepository.EditFeature(editFeature, vm.ReturnTeam, vm.ReturnUser);
            return RedirectToAction(MVC.ProjectAdmin.ActionNames.ProjectFeatures, new { projectName = projectName });
        }

        /// <summary>
        /// Metoda wyświetlająca widok, który umożliwia zmianę statusu funkcjonalności.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Nazwa projektu.</param>
        /// <param name="featureId">Identyfikator funkcjonalności.</param>
        /// <returns>Widok umożliwiający zmianę statusu funkcjonalności.</returns>
        [Authorize]
        public virtual ViewResult ChangeFeatureStatus(string projectName, int featureId)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            Feature feature = projectRepository.GetFeatureById(featureId);
            ProjectAdminChangeFeatureStatusViewModel vm = ProjectAdminChangeFeatureStatusViewModel.Convert(feature, projectName);
            return View(vm);
        }

        /// <summary>
        /// Metoda HttpPost zmieniająca status funkcjonalności.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="vm">Model widokowy zmiany statusu funkcjonalności.</param>
        /// <returns>Akcja wyświetlająca wszystkie funkcjonalności w projekcie.</returns>
        [Authorize]
        [HttpPost]
        public virtual ActionResult ChangeFeatureStatus(ProjectAdminChangeFeatureStatusViewModel vm)
        {
            string projectName = vm.ProjectName;
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            Feature feature = projectRepository.GetFeatureById(vm.FeatureId);
            if (feature.Status != (byte)StatusName.ConvertFromString(vm.ReturnStatus))
            {
                User user = userRepository.GetUserByLogin(User.Identity.Name);
                StatusChange sc = ProjectAdminChangeFeatureStatusViewModel.Convert(vm, feature, user.Id);
                projectRepository.ChangeFeatureStatus(feature, sc);
            }
            return RedirectToAction(MVC.ProjectAdmin.ActionNames.ProjectFeatures, new { projectName = projectName });
        }

        #endregion

        #region Zarządzanie taskami

        [Authorize]
        public virtual ViewResult ProjectTasks(string projectName)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            int projectId = projectRepository.GetProjectId(projectName);
            Task[] tasks = projectRepository.GetProjectTasks(projectId);
            string[] receivers = new string[tasks.Length];
            for (int i = 0; i < receivers.Length; i++)
                receivers[i] = userRepository.GetUserById(tasks[i].UserId).Login;
            ProjectAdminProjectTaskViewModel[] vmTab = ProjectAdminProjectTaskViewModel.Convert(tasks, receivers);
            ViewData["ProjectName"] = projectName;
            return View(vmTab);
        }

        [Authorize]
        public virtual ViewResult AddNewTask(string projectName)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            int projectId = projectRepository.GetProjectId(projectName);
            Feature[] features = projectRepository.GetProjectFeatures(projectId);
            User[] users;
            UserRole[] userRoles;
            projectRepository.GetProjectUsers(out users, out userRoles, projectName);
            ProjectAdminAddNewTaskViewModel vm = new ProjectAdminAddNewTaskViewModel();
            vm.ProjectName = projectName;

            // uzupełnienie odpowiednich list
            vm.FeatureList = new List<SelectListItem>(features.Length + 1);
            SelectListItem noFeature = new SelectListItem { Selected = true, Text = ProjectAdminAddNewTaskViewModel.NoFeature };
            vm.FeatureList.Add(noFeature);
            for (int i = 0; i < features.Length; i++)
                vm.FeatureList.Add(new SelectListItem { Text = features[i].Name });
            vm.UserList = new List<SelectListItem>(users.Length);
            for (int i = 0; i < users.Length; i++)
                vm.UserList.Add(new SelectListItem { Text = users[i].Login });

            // domyślna data dzisiaj plus tydzien
            vm.PlannedEndDate = DateTime.Now.AddDays(7);
            return View(vm);
        }

        [Authorize]
        [HttpPost]
        public virtual ActionResult AddNewTask(ProjectAdminAddNewTaskViewModel vm)
        {
            string projectName = vm.ProjectName;
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            int projectId = projectRepository.GetProjectId(projectName);
            // sprawdzenie czy nie istnieje juz nazwa taska
            Task[] tasks = projectRepository.GetProjectTasks(projectId);
            for (int i = 0; i < tasks.Length; i++)
                if (vm.Name == tasks[i].Name)
                {
                    ModelState.AddModelError("Name", "Już isnieje w projekcie zadanie o podanej nazwie");
                    // uzupełnienie odpowiednich list
                    Feature[] features = projectRepository.GetProjectFeatures(projectId);
                    User[] users;
                    UserRole[] userRoles;
                    projectRepository.GetProjectUsers(out users, out userRoles, projectName);

                    vm.FeatureList = new List<SelectListItem>(features.Length + 1);
                    SelectListItem noFeature = new SelectListItem { Selected = true, Text = ProjectAdminAddNewTaskViewModel.NoFeature };
                    vm.FeatureList.Add(noFeature);
                    for (int j = 0; j < features.Length; j++)
                        vm.FeatureList.Add(new SelectListItem { Text = features[j].Name });
                    vm.UserList = new List<SelectListItem>(users.Length);
                    for (int j = 0; j < users.Length; j++)
                        vm.UserList.Add(new SelectListItem { Text = users[j].Login });
                    return View(vm);
                }
            int? featureId = null;
            if (vm.ReturnFeature != ProjectAdminAddNewTaskViewModel.NoFeature)
                featureId = projectRepository.GetFeatureByName(vm.ReturnFeature, projectId).Id;
            User user = userRepository.GetUserByLogin(vm.ReturnUser);
            Task task = ProjectAdminAddNewTaskViewModel.Convert(vm, projectId, user.Id, featureId);
            int creatorId = userRepository.GetUserByLogin(User.Identity.Name).Id;
            projectRepository.AddNewTask(task, creatorId);
            return RedirectToAction(MVC.ProjectAdmin.ActionNames.ProjectTasks, new { projectName = projectName });
        }

        /// <summary>
        /// Metoda generująca widok pozwalający edytować zadanie.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Nazwa projektu.</param>
        /// <param name="taskId">Identyfikator zadania do edycji.</param>
        /// <returns>Widok pozwalający edytować zadanie.</returns>
        [Authorize]
        public virtual ViewResult EditTask(string projectName, int taskId)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            Task task = projectRepository.GetTaskById(taskId);
            ProjectAdminEditTaskViewModel vm = ProjectAdminEditTaskViewModel.Convert(task, projectName);

            // uzupelnienie odpowiednich list modelu widokowego
            int projectId = projectRepository.GetProjectId(projectName);
            Feature[] features = projectRepository.GetProjectFeatures(projectId);
            User[] users;
            UserRole[] userRoles;
            projectRepository.GetProjectUsers(out users, out userRoles, projectName);

            // lista releasów
            vm.FeatureList = new List<SelectListItem>(features.Length + 1);
            SelectListItem noFeature = new SelectListItem { Text = ProjectAdminAddNewTaskViewModel.NoFeature };
            if (task.FeatureId == null)
                noFeature.Selected = true;
            else
            {
                Feature feature = projectRepository.GetFeatureById((int)task.FeatureId);
                SelectListItem actualFeature = new SelectListItem { Selected = true, Text = feature.Name };
                vm.FeatureList.Add(actualFeature);
                noFeature.Selected = false;
            }
            vm.FeatureList.Add(noFeature);
            for (int i = 0; i < features.Length; i++)
            {
                if (features[i].Id != task.FeatureId)
                    vm.FeatureList.Add(new SelectListItem { Text = features[i].Name });
            }
            // lista przypisanych uzytkownikow, zakłądamy że żaden user nie ma id równe -1
            vm.UserList = new List<SelectListItem>(users.Length);
            User actualUser = userRepository.GetUserById(task.UserId);
            SelectListItem actualUserItem = new SelectListItem { Selected = true, Text = actualUser.Login };
            int actualUserId = actualUser.Id;
            vm.UserList.Add(actualUserItem);
            for (int i = 0; i < users.Length; i++)
            {
                if (users[i].Id != actualUserId)
                    vm.UserList.Add(new SelectListItem { Text = users[i].Login });
            }
            return View(vm);
        }

        /// <summary>
        /// Metoda HttpPost do edycji zadania.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="vm">Model z widoku.</param>
        /// <returns>Akcja wyświetlająca listę zadań.</returns>
        [Authorize]
        [HttpPost]
        public virtual ActionResult EditTask(ProjectAdminEditTaskViewModel vm)
        {
            string projectName = vm.ProjectName;
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            int projectId = projectRepository.GetProjectId(projectName);
            // sprawdzenie czy nie istnieje juz nazwa funkcjonalności
            Task[] tasks = projectRepository.GetProjectTasks(projectId);
            for (int j = 0; j < tasks.Length; j++)
                if (vm.Name == tasks[j].Name && vm.TaskId != tasks[j].Id)
                {
                    ModelState.AddModelError("Name", "Istnieje w projekcie zadanie o podanej nazwie");
                    // uzupelnienie odpowiednich list modelu widokowego
                    Feature[] features = projectRepository.GetProjectFeatures(projectId);
                    User[] users;
                    UserRole[] userRoles;
                    projectRepository.GetProjectUsers(out users, out userRoles, projectName);
                    Task task = projectRepository.GetTaskById(vm.TaskId);
                    // lista funkcjonalnosci
                    vm.FeatureList = new List<SelectListItem>(features.Length + 1);
                    SelectListItem noFeature = new SelectListItem { Text = ProjectAdminAddNewTaskViewModel.NoFeature };
                    if (task.FeatureId == null)
                        noFeature.Selected = true;
                    else
                    {
                        Feature feature = projectRepository.GetFeatureById((int)task.FeatureId);
                        SelectListItem actualFeature = new SelectListItem { Selected = true, Text = feature.Name };
                        vm.FeatureList.Add(actualFeature);
                        noFeature.Selected = false;
                    }
                    vm.FeatureList.Add(noFeature);
                    for (int i = 0; i < features.Length; i++)
                    {
                        if (features[i].Id != task.FeatureId)
                            vm.FeatureList.Add(new SelectListItem { Text = features[i].Name });
                    }

                    // lista przypisanych uzytkownikow
                    vm.UserList = new List<SelectListItem>(users.Length);
                    User actualUser = userRepository.GetUserById(task.UserId);
                    SelectListItem actualUserItem = new SelectListItem { Selected = true, Text = actualUser.Login };
                    vm.UserList.Add(actualUserItem);
                    for (int i = 0; i < users.Length; i++)
                    {
                        if (users[i].Id != actualUser.Id)
                            vm.UserList.Add(new SelectListItem { Text = users[i].Login });
                    }
                    vm.PriorityList = new PriorityViewModel(PriorityViewModel.ConvertFromString(PriorityViewModel.ConvertFromByte(task.Priority)));
                    return View(vm);
                }
            // czas na edycje zadania
            int? featureId = null;
            if (vm.ReturnFeature != ProjectAdminAddNewTaskViewModel.NoFeature)
            {
                Feature feature = projectRepository.GetFeatureByName(vm.ReturnFeature, projectId);
                featureId = feature.Id;
            }
            Task editedTask = ProjectAdminEditTaskViewModel.Convert(vm, userRepository.GetUserByLogin(vm.ReturnUser).Id, featureId);
            projectRepository.EditTask(editedTask);
            return RedirectToAction(MVC.ProjectAdmin.ActionNames.ProjectTasks, new { projectName = projectName });
        }

        /// <summary>
        /// Metoda wyświetlająca widok, który umożliwia zmianę statusu zadania.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Nazwa projektu.</param>
        /// <param name="taskId">Identyfikator zadania.</param>
        /// <returns>Widok umożliwiający zmianę statusu zadania.</returns>
        [Authorize]
        public virtual ViewResult ChangeTaskStatus(string projectName, int taskId)
        {
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            Task task = projectRepository.GetTaskById(taskId);
            ProjectAdminChangeTaskStatusViewModel vm = ProjectAdminChangeTaskStatusViewModel.Convert(task, projectName);
            return View(vm);
        }

        /// <summary>
        /// Metoda HttpPost zmieniająca status zadania.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="vm">Model widokowy zmiany statusu zadania.</param>
        /// <returns>Akcja wyświetlająca wszystkie zadania w projekcie.</returns>
        [Authorize]
        [HttpPost]
        public virtual ActionResult ChangeTaskStatus(ProjectAdminChangeTaskStatusViewModel vm)
        {
            string projectName = vm.ProjectName;
            if (!CheckAccess(projectName))
                throw new Exception("Brak dostępu");
            Task task = projectRepository.GetTaskById(vm.TaskId);
            if (task.Status != (byte)StatusName.ConvertFromString(vm.ReturnStatus))
            {
                User user = userRepository.GetUserByLogin(User.Identity.Name);
                StatusChange sc = ProjectAdminChangeTaskStatusViewModel.Convert(vm, task, user.Id);
                projectRepository.ChangeTaskStatus(task, sc);
            }
            return RedirectToAction(MVC.ProjectAdmin.ActionNames.ProjectTasks, new { projectName = projectName });
        }

        #endregion
    }
}
